<?php

namespace app\common\utils;

use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData;

class Jwt
{
    private $config;

    public function __construct()
    {
        $this->config = [
            "audience" => config('setting.domain'),//接收人
            'id' => config('setting.jwt_id'),
            'sign' => config('setting.jwt_salt'),//签名密钥
            'issuer' => config('setting.domain'),//签发人
            'expire' => config('setting.jwt_expire_in'), //有效期
        ];
    }

    //生成token
    public function generateToken($user_id)
    {
        //签名对象
        $signer = new Sha256();
        //获取当前时间戳
        $time = time();
        //设置签发人、接收人、唯一标识、签发时间、立即生效、过期时间、用户id、签名
        $token = (new Builder())->issuedBy($this->config['issuer'])
            ->canOnlyBeUsedBy($this->config['audience'])
            ->identifiedBy($this->config['id'], true)
            ->issuedAt($time)
            ->canOnlyBeUsedAfter($time - 1)
            ->expiresAt($time + $this->config['expire'])
            ->with('user_id', $user_id)
            ->sign($signer, $this->config['sign'])
            ->getToken();
        return (string)$token;
    }

    //从token中获取用户id （包含token的校验）
    public function parseToken($token = null)
    {
        $user_id = null;

        $token = empty($token) ? Token::getBearToken() : $token;

        if (!empty($token)) {
            //为了注销token 加以下if判断代码
            $delete_token = cache('delete_token') ?: [];
            if (in_array($token, $delete_token)) {
                //token已被删除（注销）
                return $user_id;
            }
            $token = (new Parser())->parse((string)$token);
            //验证token
            $data = new ValidationData();
            $data->setIssuer($this->config['issuer']);//验证的签发人
            $data->setAudience($this->config['audience']);//验证的接收人
            $data->setId($this->config['id']);//验证token标识

            if (!$token->validate($data)) {
                //token验证失败
                return $user_id;
            }

            //验证签名
            $signer = new Sha256();
            if (!$token->verify($signer, $this->config['sign'])) {
                //签名验证失败
                return $user_id;
            }
            //从token中获取用户id
            $user_id = $token->getClaim('user_id');
        }

        return $user_id;
    }
}